﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace Scaffold
{
	public class ModBus64
	{
		SerialPort sp;
		const int BUFF_SIZE = 16;
		byte[] buf;
		byte boardAddr;
		public static void DisplayBuf(byte[] buf)
		{
			for (int i = 0; i < buf.Length; i++)
			{
				Console.Write("{0:X} ", buf[i]);
			}
			Console.WriteLine();
		}
		public ModBus64(string portName, byte boardAddr)
		{
			sp = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One);
			this.boardAddr = boardAddr;
		}

		public void Open()
		{
			sp.Open();
		}
		public void Close()
		{
			sp.Close();
		}
		//查询48路输入口的状态
		public Dictionary<string, List<byte>> ReadStatus()
		{
			buf = new byte[BUFF_SIZE];
			buf[1] = 0x5A;
			buf[2] = 0x41;
			buf[3] = boardAddr;
			buf[4] = 0x07;
			buf[15] = CheckSum();
			sp.Write(buf, 0, BUFF_SIZE);
			sp.DiscardInBuffer();
			Dictionary<string, List<byte>> data = new Dictionary<string, List<byte>>();
			List<byte> X = new List<byte>(48);
			System.Threading.Thread.Sleep(100);

			buf = new byte[BUFF_SIZE];
			sp.Read(buf, 0, BUFF_SIZE);
			DisplayBuf(buf);
			var tmp = buf.Skip(6).Take(6).ToArray();
			for (int i = 0; i < 48; i++)
			{
				int j = i / 8;
				int k = i % 8;
				X.Add((tmp[j] & (1 << k)) == 0 ? (byte)0 : (byte)255);
			}
			data.Add("48X", X);
			data.Add("4Y", buf.Skip(5).Take(1).ToList());
			return data;
		}
		//向4路输出口同时写数据（一次完成）
		public void Write(byte data)
		{
			buf = new byte[BUFF_SIZE];
			buf[1] = 0x5A;
			buf[2] = 0x41;
			buf[3] = boardAddr;
			buf[4] = 0x03;
			buf[5] = data;
			buf[15] = CheckSum();
			sp.Write(buf, 0, BUFF_SIZE);
			System.Threading.Thread.Sleep(100);
		}
		private byte CheckSum()
		{
			int sum = 0;
			for (int i = 0; i < BUFF_SIZE - 1; i++)
			{
				sum += buf[i];
			}
			return (byte)(sum % 256);
		}
	}
	public class SignalHelper
	{
		ModBus64 modbus;
		Dictionary<string, List<byte>> lastState;
		public SignalHelper(string portName, byte boardAddr)
		{
			modbus = new ModBus64(portName, boardAddr);
			lastState = new Dictionary<string, List<byte>>();
			lastState["4Y"] = new List<byte>() { 0 };
			lastState["48X"] = new List<byte>(48);
		}
		public void WaitForInputState(int port, bool state)
		{
			Console.Write($"等待{port}号变为{state}...");
			for (; ; )
			{
				lastState = modbus.ReadStatus();
				var s = lastState["48X"];
				if ((s[port] > 0) == state)
				{
					Console.WriteLine($"OK!");
					return;
				}
			}
		}
		public void Write(int port, bool data)
		{
			Console.WriteLine($"向{port}号写{data}");
			var Y = lastState["4Y"][0];
			if (data)
			{
				Y |= (byte)(1 << port);
			}
			else
			{
				Y &= (byte)((~(1 << 5))-(1<<port) );
			}
			lastState["4Y"] = new List<byte>() { Y };
			//Console.WriteLine(Y);
			modbus.Write(Y);
		}

	}

}
